//
// Created by sally on 24-10-27.
//

#ifndef TIMER_WHEEL_H
#define TIMER_WHEEL_H
#include <array>
#include <cstdint>
#include <list>
#include <memory>
#include "TimeTask.h"
#include "TimerConfig.h"
#include <string>

#include "Task_Result.h"


namespace  whq::timer
{
    //提前声明一个ASIO的异步线程池
    class AsyncThreadPool;
    using ListTaskPtr = std::list<std::shared_ptr<TimeTask>>;
    //槽SLOT是从0开始的
    template<int SLOT>
    class SingleWheel
    {
    public:
        explicit SingleWheel();
        ~SingleWheel() = default;

        //添加任务的函数,这是普通任务的插入，按照FIFO的原则
        void add(int insert_slot,std::shared_ptr<TimeTask> && sp_task );
        void add_High_priority(int insert_solt,std::shared_ptr<TimeTask> && sp_task);

        //时间轮的模拟滚动函数
        std::pair<ListTaskPtr,bool> tick();
        std::pair<ListTaskPtr,bool> degrade();

        uint8_t getSlot() const {return cur_slot;}
    private:
        //任务弹出函数
        ListTaskPtr Task_pop_up(uint8_t cur_slot);
    private:

        //单一轮需要有时间槽，表示当前的时间走到哪里了
        uint8_t     cur_slot;
        //每个槽下面还需要有任务链表，或任务数组
        std::array<ListTaskPtr,SLOT> task_list;
    };




    class Timer_wheel
    {
    public:
        static Timer_wheel& GetInstance();
        void destory()
        {
            alive = false;
            task_set.clear();
        }

        ~Timer_wheel();

        Task_Result add_loop_timer(const std::string &name,uint32_t milliSeconds_timeout,std::function<bool(void)> &&func);
        Task_Result add_once_timer(const std::string& name, uint32_t milliseconds_timeout, std::function<bool()>&& func);
        void delete_timer(const std::string &name);
    private:
        Timer_wheel();
        void tick();
        //这个函数是给循环任务使用的,这是在内部进行重新添加的
        void add_timer(std::shared_ptr<TimeTask> &&tw);

        Task_Result add_timer(const std::string &name,uint32_t millseconds_timeout,std::function<bool(void)> &&func,bool is_loop);

        void load_timer(std::shared_ptr<TimeTask> && p_tt);

        //写一个返回当前所有的时间轮的时间指针的位置的函数
        std::array<uint8_t,5> get_time_wheel_slot();
    private:
        AsyncThreadPool&        ahp;
        const tmpoint           runTime;    //这是时间轮开始的运行时间
        std::atomic_bool        alive;      //这是时间轮的运行状态
        //主从轮
        std::unique_ptr<SingleWheel<TVR_SIZE>>  First_Wheel;

        std::array<std::unique_ptr<SingleWheel<TNR_SIZE>>,4>  Second_Wheel;

        //使用order_map来完成任务的保存，通过这种可以判断任务是否被删除了
        std::unordered_map<std::string,std::shared_ptr<TimeTask>> task_set; //需要循环执行的任务是放在这里面的
        std::recursive_mutex       m_mutex_;        //递归锁
    };
}




#endif //TIMER_WHEEL_H
